home *** CD-ROM | disk | FTP | other *** search
/ BBS Toolkit / BBS Toolkit.iso / doors_1 / doorskl3.zip / XBBSMSG.ZIP / GETPUT.C < prev    next >
C/C++ Source or Header  |  1991-12-14  |  17KB  |  629 lines

  1. /* primitives for manipulating XBBS message areas
  2.    this code hacked out in one sitting by Mark Kimes 06/25/91
  3.    compiles; no guarantee that it works. */
  4.  
  5. /* I'm not quite sure how locking works under DOS-OS/2.  Does the seek
  6.    to a locked record fail, or the read/write?  This code assumes that
  7.    either could fail.  It locks for all writes, no reads. */
  8.  
  9. #ifndef __TURBOC__
  10.     #define INCL_DOS
  11.     #include <os2.h>            /* for DosSleep() */
  12.     #include <sys/locking.h>
  13. #endif
  14. #include <sys/types.h>
  15. #include <sys/stat.h>
  16. #include <io.h>
  17. #include <fcntl.h>
  18. #include <share.h>
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include <errno.h>
  23. #include "xmsg.h"
  24.  
  25. #ifdef __TURBOC__
  26.     #define LK_LOCK     1
  27.     #define LK_UNLCK    2
  28.     #define DosSleep(x) sleep(1)
  29.     /* replacement for MSC's locking() in this module */
  30.     int pascal locking (int handle,int type,long length);  
  31.     #define _fastcall pascal
  32. #endif
  33.  
  34.  
  35. /* external variables referenced */
  36.  
  37. extern char *msgpath;
  38.  
  39. /* external functions referenced */
  40.  
  41. /* global variables created here */
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49. int _fastcall get_text (char **hold,XMSG *msg,unsigned int areano,
  50.                         unsigned int messno) {
  51.  
  52.  /* loads text for XMSG *msg message #messno from areano #areano into
  53.     **hold (allocates here, caller must free).  Can modify *msg if
  54.     message hasn't been previously TREATED.  UNLZSSs if message was
  55.     compressed. */
  56.  
  57.     int          once,reduced = 0,handle;
  58.     char         *tempo;
  59.     char         filename[257];
  60.     unsigned int temp,len;
  61.     long         pos;
  62.  
  63.  
  64.     if(!msg->length) return MSG_NOTEXT;
  65.     if(msg->length > 65500U) msg->length = 65500U;
  66.     *hold = NULL;
  67.  
  68.     /* open text file */
  69.  
  70.     sprintf(filename,"%sXTEXT.%03x",msgpath,areano);
  71.     once = 0;
  72.     while ((handle = sopen(filename,O_RDONLY | O_BINARY, SH_DENYNO,S_IREAD | S_IWRITE)) == -1) {
  73.         if (errno == EACCES) {
  74.             once++;
  75.             if (once > 10) {
  76.                 return MSG_NOACCESS;
  77.             }
  78.             DosSleep(1000L);
  79.         }
  80.         else {
  81.             return MSG_NOOPEN;
  82.         }
  83.     }
  84.  
  85.     temp = msg->length;
  86.  
  87.     /* seek to position */
  88.  
  89.     once = 0;
  90.     while (lseek(handle,msg->start,SEEK_SET) == -1L) {
  91.         if (once < 10) {
  92.             once++;
  93.             DosSleep(1000L);
  94.         }
  95.         else {
  96.             close(handle);
  97.             return MSG_NOSEEK;
  98.         }
  99.     }
  100.  
  101.     /* load text */
  102.  
  103.     if(msg->length > 65500U) msg->length = 65500U;
  104.  
  105. ReTry:
  106.     *hold = (char *)malloc(msg->length + 1);
  107.     if (*hold == NULL) {
  108.         if (msg->length > 1024 && !(msg->m_attr & MSGPACKED)) {
  109.             msg->length -= 256;
  110.             reduced = 1;
  111.             goto ReTry;
  112.         }
  113.         else {
  114.             close(handle);
  115.             return MSG_NOMEM;
  116.         }
  117.     }
  118.  
  119.     memset(*hold,0,msg->length);
  120.  
  121.     once = 0;
  122.     for(;;) {
  123.         pos = tell(handle);
  124.         len = (unsigned int)read(handle,*hold,msg->length);
  125.         if(!len || len == 65535U) {
  126.             once++;
  127.             if(once < 10) {
  128.                 lseek(handle,pos,SEEK_SET);
  129.                 DosSleep(500L);
  130.             }
  131.             else {
  132.                 close(handle);
  133.                 free(*hold);
  134.                 *hold = NULL;
  135.                 return MSG_NOREAD;
  136.             }
  137.         }
  138.         else if(len < (msg->length - 1)) {
  139.             reduced = 1;
  140.             break;
  141.         }
  142.         else break;
  143.     }
  144.  
  145.     close(handle);
  146.     tempo = *hold;
  147.     tempo[msg->length - 1] = 0;
  148.     tempo[msg->length] = 0;
  149.  
  150.     /* treat text if necessary */
  151.  
  152.     tempo = *hold;
  153.     if(!(msg->m_attr & MSGTREATED) &&
  154.        /* !(currarea->attr & ANSI) && */ !(msg->m_attr & MSGPACKED)) {
  155.         while (*tempo) {
  156.             if(*tempo == '\x8d' || *tempo == '\n') {
  157.                 memmove(tempo,&tempo[1],msg->length - ((unsigned int)tempo -
  158.                         (unsigned int)*hold));
  159.                 msg->length--;
  160.                 if(!msg->length) break;
  161.             }
  162.             else tempo++;
  163.         }
  164.         if(*(tempo - 1) != '\r' && tempo > *hold) {
  165.             *tempo = '\r';
  166.             tempo[1] = 0;
  167.         }
  168.  
  169.         /* rewrite treated text */
  170.  
  171.         if(!reduced && temp > ((unsigned int)strlen(*hold) + 1) && **hold) {
  172.             msg->length = (unsigned int)strlen(*hold) + 1;
  173.             sprintf(filename,"%sXTEXT.%03x",msgpath,areano);
  174.         if ((handle = sopen(filename,O_RDWR | O_BINARY, SH_DENYNO,S_IWRITE | S_IREAD)) == -1)
  175.               goto OkayThenDont;
  176.             once = 0;
  177.             while (lseek(handle,msg->start,SEEK_SET) == -1L) {
  178.                 if (once < 10) {
  179.                     once++;
  180.                     DosSleep(100L);
  181.                 }
  182.                 else {
  183.                     close(handle);
  184.                     goto OkayThenDont;
  185.                 }
  186.             }
  187.             if(!locking(handle,LK_LOCK,(long)(msg->length + 1))) {
  188.                 write(handle,*hold,strlen(*hold));
  189.                 write(handle,"\0",1);
  190.                 lseek(handle,msg->start,SEEK_SET);
  191.                 locking(handle,LK_UNLCK,(long)(msg->length + 1));
  192.                 close(handle);
  193.  
  194.                 /* rewrite header for treated text */
  195.  
  196.                 msg->m_attr |= MSGTREATED;
  197.                 put_mess(msg,areano,messno);
  198.                 temp = msg->length;
  199.             }
  200.         }
  201.     }
  202.  
  203.     /* UnLZSS compressed text */
  204.  
  205.     if(msg->m_attr & MSGPACKED && !reduced) {
  206.        if(unpack_msg(msg,hold) == NULL) {   /* extern routine */
  207.            if(*hold) free(*hold);
  208.            *hold = NULL;
  209.            return MSG_NOUNLZSS;
  210.        }
  211.     }
  212.  
  213.     /* wrapup */
  214.  
  215. OkayThenDont:
  216.  
  217.     msg->length = temp;
  218.     if(reduced) return MSG_REDUCED;
  219.     return MSG_NOERR;
  220. }
  221.  
  222.  
  223.  
  224.  
  225. int _fastcall append_text (XMSG *msg,char *hold,unsigned int areano,
  226.                            unsigned int messno) {
  227.  
  228.  /* appends text for XMSG *msg, message #messno in area #areano with
  229.     text in *hold.  updates msg->length and msg->start */
  230.  
  231.     unsigned int messlen = 0;
  232.     int          handle,once;
  233.     long         pos;
  234.     char         filename[257];
  235.  
  236.  
  237.     if (hold == NULL || !*hold) return MSG_NOTEXT;
  238.  
  239.     /* open text file */
  240.  
  241.     sprintf(filename,"%sXTEXT.%03x",msgpath,areano);
  242.     once = 0;
  243.     while ((handle = sopen(filename,O_RDWR | O_BINARY | O_CREAT, SH_DENYNO,S_IWRITE | S_IREAD)) == -1) {
  244.         if (errno == EACCES) {
  245.             if(once < 10) {
  246.                 DosSleep(1000L);
  247.                 once++;
  248.             }
  249.             else {
  250.                 return MSG_NOACCESS;
  251.             }
  252.         }
  253.         else return MSG_NOOPEN;
  254.     }
  255.  
  256.     /* seek to position */
  257.  
  258. SeekAgain:
  259.  
  260.     once = 0;
  261.     while ((pos = lseek(handle,0L,SEEK_END)) == -1L) {
  262.         if (once < 10) {
  263.             once++;
  264.             DosSleep(100L);
  265.         }
  266.         else {
  267.             close(handle);
  268.             return MSG_NOSEEK;
  269.         }
  270.     }
  271.  
  272.     /* lock, write, unlock */
  273.  
  274.     if(!locking(handle,LK_LOCK,65535L)) {
  275.         if(lseek(handle,0L,SEEK_END) != pos) {
  276.             lseek(handle,pos,SEEK_SET);
  277.             locking(handle,LK_UNLCK,65535L);
  278.             goto SeekAgain;
  279.         }
  280.         pos = tell(handle);
  281.         messlen += write(handle,hold,sizeof(char) * strlen(hold));
  282.         write(handle,"\0",1);
  283.         lseek(handle,pos,SEEK_SET);
  284.         locking(handle,LK_UNLCK,65535L);
  285.         messlen += 2;
  286.         msg->length = messlen;
  287.         msg->start = pos;
  288.         if(msg->length > 65500U) msg->length = 65500U;
  289.         close(handle);
  290.         return MSG_NOERR;
  291.     }
  292.  
  293.     close(handle);
  294.     return MSG_NOLOCK;
  295. }
  296.  
  297.  
  298.  
  299.  
  300. int _fastcall replace_text (XMSG *msg,char *hold,unsigned int areano,
  301.                             unsigned int messno) {
  302.  
  303.  /* call this to replace text for XMSG *msg, message #messno, areano
  304.     #areano with text in *hold.  Will append instead of replace if
  305.     there's not enough room in existing allocation.  Updates msg->length
  306.     (and msg->start) */
  307.  
  308.     unsigned int messlen = 0;
  309.     int          handle,once;
  310.     char         filename[257];
  311.  
  312.  
  313.     if (hold == NULL || !*hold) return MSG_NOTEXT;
  314.  
  315.     /* decide whether to append or replace */
  316.  
  317.     if(strlen(hold) > msg->length - 2)
  318.       return append_text(msg,hold,areano,messno);
  319.  
  320.     /* open text file */
  321.  
  322.     sprintf(filename,"%sXTEXT.%03x",msgpath,areano);
  323.     once = 0;
  324.     while ((handle = sopen(filename,O_RDWR | O_BINARY | O_CREAT, SH_DENYNO,S_IWRITE | S_IREAD)) == -1) {
  325.         if (errno == EACCES) {
  326.             if(once < 10) {
  327.                 DosSleep(1000L);
  328.                 once++;
  329.             }
  330.             else {
  331.                 return MSG_NOACCESS;
  332.             }
  333.         }
  334.         else return MSG_NOOPEN;
  335.     }
  336.  
  337.     /* seek to position */
  338.  
  339.     once = 0;
  340.     while (lseek(handle,msg->start,SEEK_SET) == -1L) {
  341.         if (once < 10) {
  342.             once++;
  343.             DosSleep(100L);
  344.         }
  345.         else {
  346.             close(handle);
  347.             return MSG_NOSEEK;
  348.         }
  349.     }
  350.  
  351.     /* lock, write, unlock */
  352.  
  353.     if(!locking(handle,LK_LOCK,65535L)) {
  354.         messlen += write(handle,hold,sizeof(char) * strlen(hold));
  355.         write(handle,"\0",1);
  356.         lseek(handle,msg->start,SEEK_SET);
  357.         locking(handle,LK_UNLCK,65535L);
  358.         messlen += 2;
  359.         msg->length = messlen;
  360.         close(handle);
  361.         if(msg->length > 65500U) msg->length = 65500U;
  362.         return MSG_NOERR;
  363.     }
  364.  
  365.     close(handle);
  366.     return MSG_NOLOCK;
  367. }
  368.  
  369.  
  370.  
  371.  
  372. int _fastcall get_mess (XMSG *msg,unsigned int areano,unsigned int messno) {
  373.  
  374.  /* fill XMSG *msg with data for message #messno in area #areano */
  375.  
  376.     int          handle,once;
  377.     char         filename[257];
  378.     unsigned int len;
  379.     long         pos;
  380.  
  381.  
  382.     /* open data file */
  383.  
  384.     sprintf(filename,"%sXDATA.%03x",msgpath,areano);
  385.     if (messno < 1) messno = 1;
  386.     once = 0;
  387.     while ((handle = sopen(filename,O_RDONLY | O_BINARY, SH_DENYNO,S_IWRITE | S_IREAD)) == -1) {
  388.         if (errno == EACCES) {
  389.             if(once < 10) {
  390.                 once++;
  391.                 DosSleep(1000L);
  392.             }
  393.             else {
  394.                 return MSG_NOACCESS;
  395.             }
  396.          }
  397.          else {
  398.              return MSG_NOOPEN;
  399.          }
  400.     }
  401.  
  402.     /* seek to position */
  403.  
  404.     once = 0;
  405.     while (lseek(handle,(long)((long)(messno - 1) * (long)sizeof(XMSG)),SEEK_SET) == -1L) {
  406.         if(once < 10) {
  407.             once++;
  408.             DosSleep(100L);
  409.         }
  410.         else {
  411.             close(handle);
  412.             return MSG_NOSEEK;
  413.         }
  414.     }
  415.  
  416.     /* read and wrapup */
  417.  
  418.     once = 0;
  419.     memset(msg,0,sizeof(XMSG));
  420.     pos = tell(handle);
  421.     for(;;) {
  422.         len = (unsigned int)read(handle,msg,sizeof(XMSG));
  423.         if(!len || len == 65535U) {
  424.             once++;
  425.             if(once < 10) {
  426.                 lseek(handle,pos,SEEK_SET);
  427.                 DosSleep(500L);
  428.             }
  429.             else {
  430.                 close(handle);
  431.                 return MSG_NOREAD;
  432.             }
  433.         }
  434.         else if(len < sizeof(XMSG)) {
  435.             close(handle);
  436.             return MSG_PARTREAD;
  437.         }
  438.         else break;
  439.     }
  440.  
  441.     close(handle);
  442.     return MSG_NOERR;
  443. }
  444.  
  445.  
  446.  
  447.  
  448. int _fastcall put_mess (USHORT cp,XMSG *msg,unsigned int areano,
  449.                         unsigned int messno) {
  450.  
  451.  /* write XMSG *msg to message #messno in area #areano */
  452.  
  453.     int          handle;
  454.     unsigned int x = 0;
  455.     char         filename[64];
  456.     long         pos;
  457.  
  458.  
  459.     /* open data file */
  460.  
  461.     sprintf(filename,"MSG/XDATA.%03x",areano);
  462.     while ((handle = sopen(filename,O_NOINHERIT | O_RDWR | O_BINARY | O_CREAT, SH_DENYNO,S_IWRITE | S_IREAD)) == -1) {
  463.         if (errno == EACCES) {
  464.             x++;
  465.             if(x > 9) {
  466.                 return MSG_NOACCESS;
  467.             }
  468.             DosSleep(1000L);
  469.          }
  470.          else {
  471.             return MSG_NOOPEN;
  472.          }
  473.     }
  474.  
  475.     if(messno) {
  476.  
  477.         /* seek to position */
  478.  
  479.         x = 0;
  480.         while (lseek(handle,(long)((long)(messno - 1) * (long)sizeof(XMSG)),SEEK_SET) == -1L) {
  481.             x++;
  482.             if(x > 9) {
  483.                 close(handle);
  484.                 return MSG_NOSEEK;
  485.             }
  486.         }
  487.  
  488.         /* lock, write, unlock */
  489.  
  490.         if(!locking(handle,LK_LOCK,(long)sizeof(XMSG))) {
  491.             write(handle,msg,sizeof(XMSG));
  492.             lseek(handle,(long)((long)(messno - 1) * (long)sizeof(XMSG)),SEEK_SET);
  493.             locking(handle,LK_UNLCK,(long)sizeof(XMSG));
  494.             close(handle);
  495.             return MSG_NOERR;
  496.         }
  497.         close(handle);
  498.         return MSG_NOLOCK;
  499.     }
  500.     else {  /* append new header */
  501.         for(;;) {
  502.             x = 0;
  503.             while((pos = lseek(handle,0L,SEEK_END)) == -1L) {
  504.                 x++;
  505.                 if(x > 9) {
  506.                     close(handle);
  507.                     return MSG_NOSEEK;
  508.                 }
  509.             }
  510.             if(!locking(handle,LK_LOCK,(long)sizeof(XMSG))) {
  511.                 if(lseek(handle,0L,SEEK_END) != pos) {
  512.                     lseek(handle,pos,SEEK_SET);
  513.                     locking(handle,LK_UNLCK,(long)sizeof(XMSG));
  514.                     continue;
  515.                 }
  516.                 write(handle,msg,sizeof(XMSG));
  517.                 lseek(handle,pos,SEEK_SET);
  518.                 locking(handle,LK_UNLCK,(long)sizeof(XMSG));
  519.                 close(handle);
  520.                 return MSG_NOERR;
  521.             }
  522.             close(handle);
  523.             return MSG_NOLOCK;
  524.         }
  525.     }
  526. }
  527.  
  528.  
  529.  
  530. int _fastcall post_message (XMSG *msg,char **hold,unsigned int areano,
  531.                             int isfile) {
  532.  
  533.     /* post a new message given header, text and area #.  if isfile is
  534.        non-zero, **hold is name of file containing text to import (note
  535.        that hold must be malloced and freeable).  text imported from a
  536.        file will be treated here; text sent in *hold will not. */
  537.  
  538.     struct stat  st;
  539.     char         filename[257],*tempo;
  540.     unsigned int nomess;
  541.     int          ret;
  542.  
  543.  
  544.     if(!hold || !*hold || !**hold) return MSG_NOTEXT;
  545.  
  546.     sprintf("%sXDATA.%03x",msgpath,areano);
  547.     if(stat(filename,&st)) st.st_size = 0L;
  548.     nomess = (unsigned int)(st.st_size / (long)sizeof(XMSG));
  549.  
  550.     if(isfile) {    /* load a file for msg text */
  551.         strcpy(filename,*hold);
  552.         free(*hold);
  553.         *hold = NULL;
  554.         ret = sopen(filename,O_RDONLY | O_BINARY, SH_DENYNO,S_IWRITE | S_IREAD);
  555.         if(ret == -1) return MSG_NOTEXT;
  556.         lseek(ret,0L,SEEK_END);
  557.         st.st_size = tell(ret);
  558.         if(!st.st_size) {
  559.             close(ret);
  560.             return MSG_NOTEXT;
  561.         }
  562.         if(st.st_size > 65500L) st.st_size = 65500L;
  563.         *hold = (char *)malloc((unsigned int)st.st_size + 1);
  564.         if(!*hold) {
  565.             close(ret);
  566.             return MSG_NOMEM;
  567.         }
  568.         lseek(ret,0L,SEEK_SET);
  569.         if((unsigned int)read(ret,*hold,(unsigned int)st.st_size) !=
  570.            (unsigned int)st.st_size) {
  571.             close(ret);
  572.             free(*hold);
  573.             *hold = NULL;
  574.             return MSG_NOREAD;
  575.         }
  576.         close(ret);
  577.         tempo = *hold;      /* "treat" text */
  578.         tempo[(unsigned int)st.st_size] = 0;
  579.         msg->length = strlen(tempo);
  580.         while (*tempo) {
  581.             if(*tempo == '\x8d' || *tempo == '\n') {
  582.                 memmove(tempo,&tempo[1],msg->length - ((unsigned int)tempo -
  583.                         (unsigned int)*hold));
  584.                 msg->length--;
  585.                 if(!msg->length) {
  586.                     return MSG_NOTEXT;
  587.                 }
  588.             }
  589.             else tempo++;
  590.         }
  591.         if(*(tempo - 1) != '\r' && tempo > *hold) {
  592.             *tempo = '\r';
  593.             tempo[1] = 0;
  594.         }
  595.     }
  596.  
  597.     ret = append_text(msg,*hold,areano,nomess + 1);
  598.     if(ret == MSG_NOERR) {
  599.         return put_mess(msg,areano,nomess + 1);
  600.     }
  601.     return ret;
  602. }
  603.  
  604.  
  605.  
  606.  
  607. #ifdef __TURBOC__
  608.  
  609. int pascal locking (int handle,int type,long length) {
  610.  
  611.     int x;
  612.  
  613.  
  614.     if(type == LK_LOCK) {
  615.         x = 0;
  616.         while(x < 10) {
  617.             if(!lock(handle,tell(handle),length)) return 0;
  618.             x++;
  619.             DosSleep(1000L);
  620.         }
  621.     }
  622.     else if(type == LK_UNLCK) {
  623.         return unlock(handle,tell(handle),length);
  624.     }
  625.     return -1;
  626. }
  627.  
  628. #endif
  629.